package com.serviceprovider.business.module.sp.transaction.valueobjects;

//~--- non-JDK imports --------------------------------------------------------

import com.serviceprovider.business.module.report.valueobjects.TransStatusVO;
import com.serviceprovider.business.module.sp.transaction.model.Batch;
import com.serviceprovider.business.module.sp.transaction.model.TransactionDetail;
import com.serviceprovider.business.module.sp.transaction.model.TransactionUserAmount;
import com.serviceprovider.business.utility.maintenance.settings.AppSettings;

import org.apache.commons.collections.Factory;
import org.apache.commons.collections.map.LazyMap;

//~--- JDK imports ------------------------------------------------------------

import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Value object for the transaction details
 *
 * @author mrduongnv@gmail.com
 */
@SuppressWarnings({ "unchecked" })
public class TransactionDetailsVO {
    private boolean       approved = false;
    private Boolean       checked  = Boolean.TRUE;
    private Integer       amount;
    Map<Integer, Integer> amounts;
    private Batch         batch;
    private Integer       customLabel1;
    private Integer       customLabel2;
    private Integer       customerBalance;
    private String        customerName;
    private Integer       customerSSN;
    Date                  dataLoadDate;
    private Integer       electronicFillingFee;
    private Integer       electronicPrepFee;
    private Integer       fedBankProductFee;
    private Integer       id;
    private Integer       miscPayments;
    Integer               moveToSSN;
    private String        originatorName;
    String                providerName;
    private Integer       selfFee;
    private Integer       serviceBureauFee;
    private Integer       serviceFee;
    private Integer       stateProductFee;
    private Integer       taxPrepFee;
    private String        traceNumber;
    private TransStatusVO transactionStatus;
    private Integer       userId;

    public TransactionDetailsVO() {
        dataLoadDate = new Date();
        amounts      = LazyMap.decorate(new HashMap<Integer, Integer>(), new Factory() {
            @Override
            public Object create() {
                return 0;
            }
        });
    }

    /**
     * Create value object from transaction details model object
     *
     * @param transactionDetail - Model object from which value object will be created
     */
    public TransactionDetailsVO(TransactionDetail transactionDetail) {
        id                   = transactionDetail.getId();
        userId               = transactionDetail.getUserId();
        batch                = transactionDetail.getBatch();
        traceNumber          = transactionDetail.getTraceNumber();
        transactionStatus    = new TransStatusVO(transactionDetail.getTransactionStatus());
        amount               = transactionDetail.getAmount();
        customerName         = transactionDetail.getCustomerName();
        originatorName       = transactionDetail.getOriginatorName();
        customerSSN          = transactionDetail.getCustomerSSN();
        selfFee              = transactionDetail.getSelfFee();
        taxPrepFee           = transactionDetail.getTaxPrepFee();
        electronicPrepFee    = transactionDetail.getElectronicPrepFee();
        electronicFillingFee = transactionDetail.getElectronicFillingFee();
        serviceBureauFee     = transactionDetail.getServiceBureauFee();
        fedBankProductFee    = transactionDetail.getFedBankProductFee();
        stateProductFee      = transactionDetail.getStateProductFee();
        customLabel1         = transactionDetail.getCustomLabel1();
        customLabel2         = transactionDetail.getCustomLabel2();
        customerBalance      = transactionDetail.getCustomerBalance();
        dataLoadDate         = transactionDetail.getDataLoadDate();
        serviceFee           = transactionDetail.getServiceFee();
        amounts              = new HashMap();

        for (TransactionUserAmount amount : transactionDetail.getTransactionUserAmount()) {
            amounts.put(amount.getUserId(), amount.getAmount());
        }
    }

    public TransactionDetailsVO(TransactionDetail transactionDetail, String providerName) {
        id                   = transactionDetail.getId();
        userId               = transactionDetail.getUserId();
        batch                = transactionDetail.getBatch();
        traceNumber          = transactionDetail.getTraceNumber();
        transactionStatus    = new TransStatusVO(transactionDetail.getTransactionStatus());
        amount               = transactionDetail.getAmount();
        customerName         = transactionDetail.getCustomerName();
        originatorName       = transactionDetail.getOriginatorName();
        customerSSN          = transactionDetail.getCustomerSSN();
        selfFee              = transactionDetail.getSelfFee();
        taxPrepFee           = transactionDetail.getTaxPrepFee();
        electronicPrepFee    = transactionDetail.getElectronicPrepFee();
        electronicFillingFee = transactionDetail.getElectronicFillingFee();
        serviceBureauFee     = transactionDetail.getServiceBureauFee();
        fedBankProductFee    = transactionDetail.getFedBankProductFee();
        stateProductFee      = transactionDetail.getStateProductFee();
        customLabel1         = transactionDetail.getCustomLabel1();
        customLabel2         = transactionDetail.getCustomLabel2();
        customerBalance      = transactionDetail.getCustomerBalance();
        dataLoadDate         = transactionDetail.getDataLoadDate();
        serviceFee           = transactionDetail.getServiceFee();
        amounts              = new HashMap();

        for (TransactionUserAmount amount : transactionDetail.getTransactionUserAmount()) {
            amounts.put(amount.getUserId(), amount.getAmount());
        }

        this.providerName = providerName;
    }

    public String getProviderName() {
        return providerName;
    }

    public void setProviderName(String providerName) {
        this.providerName = providerName;
    }

    public Integer getMoveToSSN() {
        return moveToSSN;
    }

    public void setMoveToSSN(Integer moveToSSN) {
        this.moveToSSN = moveToSSN;
    }

    public Map<Integer, Integer> getAmounts() {
        return amounts;
    }

    public void setAmounts(Map<Integer, Integer> amounts) {
        this.amounts = amounts;
    }

    public Integer getTotalPayeeAmount() {
        if (amounts == null) {
            return 0;
        }

        Integer total = 0;

        for (Integer amount : amounts.values()) {
            total += amount;
        }

        return amount;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public Batch getBatch() {
        return batch;
    }

    public void setBatch(Batch batch) {
        this.batch = batch;
    }

    public String getTraceNumber() {
        return traceNumber;
    }

    public void setTraceNumber(String traceNumber) {
        this.traceNumber = traceNumber;
    }

    public TransStatusVO getTransactionStatus() {
        return transactionStatus;
    }

    public void setTransactionStatus(TransStatusVO transactionStatus) {
        this.transactionStatus = transactionStatus;
    }

    public Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public String getOriginatorName() {
        return originatorName;
    }

    public void setOriginatorName(String originatorName) {
        this.originatorName = originatorName;
    }

    public Integer getCustomerSSN() {
        return customerSSN;
    }

    public void setCustomerSSN(Integer customerSSN) {
        this.customerSSN = customerSSN;
    }

    public Integer getSelfFee() {
        return selfFee;
    }

    public void setSelfFee(Integer selfFee) {
        this.selfFee = selfFee;
    }

    public Integer getTaxPrepFee() {
        return taxPrepFee;
    }

    public void setTaxPrepFee(Integer taxPrepFee) {
        this.taxPrepFee = taxPrepFee;
    }

    public Integer getElectronicPrepFee() {
        return electronicPrepFee;
    }

    public void setElectronicPrepFee(Integer electronicPrepFee) {
        this.electronicPrepFee = electronicPrepFee;
    }

    public Integer getElectronicFillingFee() {
        return electronicFillingFee;
    }

    public void setElectronicFillingFee(Integer electronicFillingFee) {
        this.electronicFillingFee = electronicFillingFee;
    }

    public Integer getServiceBureauFee() {
        return serviceBureauFee;
    }

    public void setServiceBureauFee(Integer serviceBureauFee) {
        this.serviceBureauFee = serviceBureauFee;
    }

    public Integer getFedBankProductFee() {
        return fedBankProductFee;
    }

    public void setFedBankProductFee(Integer fedBankProductFee) {
        this.fedBankProductFee = fedBankProductFee;
    }

    public Integer getStateProductFee() {
        return stateProductFee;
    }

    public void setStateProductFee(Integer stateProductFee) {
        this.stateProductFee = stateProductFee;
    }

    public Integer getServiceFee() {
        return serviceFee;
    }

    public void setServiceFee(Integer serviceFee) {
        this.serviceFee = serviceFee;
    }

    public Integer getCustomLabel1() {
        return customLabel1;
    }

    public void setCustomLabel1(Integer customLabel1) {
        this.customLabel1 = customLabel1;
    }

    public Integer getCustomLabel2() {
        return customLabel2;
    }

    public void setCustomLabel2(Integer customLabel2) {
        this.customLabel2 = customLabel2;
    }

    public Integer getCustomerBalance() {
        return customerBalance;
    }

    public void setCustomerBalance(Integer customerBalance) {
        this.customerBalance = customerBalance;
    }

    public Date getDataLoadDate() {
        return dataLoadDate;
    }

    public void setDataLoadDate(Date dataLoadDate) {
        this.dataLoadDate = dataLoadDate;
    }

    public boolean isApproved() {
        return approved;
    }

    public void setApproved(boolean approved) {
        this.approved = approved;
    }

    public Boolean getChecked() {
        return checked;
    }

    public void setChecked(Boolean checked) {
        this.checked = checked;
    }

    public Integer getMiscPayments() {
        return miscPayments;
    }

    public void setMiscPayments(Integer miscPayments) {
        this.miscPayments = miscPayments;
    }

    /**
     * Create list of value objects from list of model objects
     *
     * @param list - List of transaction details model object
     * @return List of transaction details value objects
     */
    public static Map<Integer, TransactionDetailsVO> fromList(List<TransactionDetail> list, String sortColumn,
            String sortOrder) {
        Map<Integer, TransactionDetailsVO> result = new HashMap<Integer, TransactionDetailsVO>();

        if ((sortColumn == null) || sortColumn.trim().isEmpty()) {
            sortColumn = AppSettings.TRANSACTION_SORT_COULMN_SSN;
        }

        if ((sortOrder == null) || sortOrder.trim().isEmpty()) {
            sortOrder = AppSettings.TRANSACTION_SORT_ORDER_ASC;
        }

        Comparator<TransactionDetail> customComparator = null;

        customComparator = new CustomComparator(sortColumn);

        if (sortOrder.equalsIgnoreCase(AppSettings.TRANSACTION_SORT_ORDER_DESC)) {
            customComparator = Collections.reverseOrder(customComparator);
        }

        Collections.sort(list, customComparator);

        int i = 1;

        for (TransactionDetail detail : list) {

            // result.put(detail.getId(), new TransactionDetailsVO(detail));
            // result.put(i, new TransactionDetailsVO(detail));
            result.put(i, new TransactionDetailsVO(detail));
            i++;
        }

        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if ((obj == null) ||!(obj instanceof TransactionDetailsVO)) {
            return false;
        }

        TransactionDetailsVO b = (TransactionDetailsVO) obj;

        return ((id == null) && (b.id == null)) || ((id != null) && id.equals(b.id));
    }

    @Override
    public int hashCode() {
        return (id != null)
               ? id.hashCode()
               : 0;
    }

    static class CustomComparator implements Comparator<TransactionDetail> {
        String defaultColumn = "";

        public CustomComparator(String column) {
            if ((column != null) &&!column.trim().isEmpty()) {
                this.defaultColumn = column;
            }
        }

        @Override
        public int compare(TransactionDetail o1, TransactionDetail o2) {
            if (defaultColumn.equalsIgnoreCase(AppSettings.TRANSACTION_SORT_COULMN_NAME)) {
                return o1.getCustomerName().compareTo(o2.getCustomerName());
            } else if (defaultColumn.equalsIgnoreCase(AppSettings.TRANSACTION_SORT_COULMN_AMOUNT)) {
                return o1.getAmount().compareTo(o2.getAmount());
            } else {
                return o1.getCustomerSSN().compareTo(o2.getCustomerSSN());
            }
        }
    }
}



